<template>
  <div class="app-container">
    <div class="header-controls">
      <el-button type="primary" @click="initViewer" :loading="initializing">
        {{ viewerInitialized ? '重新初始化' : '初始化 DICOM 查看器' }}
      </el-button>

      <el-select
        v-model="seriesInstanceUid"
        placeholder="选择序列实例"
        style="width: 300px; margin-right: 10px;"
        @change="handleSeriesChange"
        :disabled="!seriesInstanceUidOptions.length"
      >
        <el-option
          v-for="series in seriesInstanceUidOptions"
          :key="series.seriseId"
          :label="series.seriseId"
          :value="series.seriseId"
        />
      </el-select>

      <el-button 
        type="primary" 
        @click="loadDicomImages" 
        :disabled="!seriesInstanceUid || !viewerInitialized"
        :loading="loading"
      >
        加载影像
      </el-button>

      <!-- 调试信息 -->
      <el-button @click="showDebugInfo = !showDebugInfo" type="text">
        {{ showDebugInfo ? '隐藏调试' : '显示调试' }}
      </el-button>
    </div>

    <!-- 调试信息 -->
    <div v-if="showDebugInfo" class="debug-info">
      <h4>调试信息:</h4>
      <div>当前图像URL: {{ currentImageUrl }}</div>
      <div>图像数量: {{ imageUrls.length }}</div>
      <div>文件类型: {{ detectedFileType }}</div>
      <div>数据大小: {{ dataSize }} bytes</div>
      <div>加载状态: {{ imageLoading ? '加载中' : '就绪' }}</div>
      <div>错误信息: {{ error }}</div>
    </div>

    <!-- 状态提示 -->
    <div v-if="loading" class="status-message">
      <el-icon class="is-loading"><Loading /></el-icon>
      正在加载 DICOM 图像...
    </div>
    
    <div v-if="initializing" class="status-message">
      <el-icon class="is-loading"><Loading /></el-icon>
      正在初始化 DICOM 查看器...
    </div>
    <div v-if="error" class="error-message">
      <el-icon><Warning /></el-icon>
      错误: {{ error }}
    </div>

    <!-- 图像控制 -->
    <div class="image-controls" v-if="currentImageIndex !== -1">
      <el-button @click="prevImage" :disabled="currentImageIndex === 0">
        上一张
      </el-button>
      <span class="image-counter">
        {{ currentImageIndex + 1 }} / {{ imageUrls.length }}
      </span>

      <el-button @click="nextImage" :disabled="currentImageIndex === imageUrls.length - 1">
        下一张
      </el-button>
      
      <!-- 图像操作 -->
      <div class="image-operations">
        <el-button @click="zoomIn">放大</el-button>
        <el-button @click="zoomOut">缩小</el-button>
        <el-button @click="resetView">重置视图</el-button>
        <el-button @click="analyzeCurrentImage" type="warning">分析图像数据</el-button>
      </div>
    </div>

    <!-- DICOM图像显示区域 -->
    <div class="viewer-container">
      <canvas 
        ref="canvasRef" 
        class="dicom-canvas"
        @wheel="handleWheel"
        @mousedown="handleMouseDown"
        @mousemove="handleMouseMove"
        @mouseup="handleMouseUp"
        @mouseleave="handleMouseUp"
      ></canvas>
      
      <!-- 加载提示 -->
      <div v-if="imageLoading" class="loading-overlay">
        <el-icon class="is-loading"><Loading /></el-icon>
        <span>正在加载图像 {{ currentImageIndex + 1 }}...</span>
        <div v-if="currentLoadMethod">使用方式: {{ currentLoadMethod }}</div>
      </div>
      
      <!-- 图像信息 -->
      <div v-if="currentImageInfo" class="image-info">
        <div>图像: {{ currentImageIndex + 1 }} / {{ imageUrls.length }}</div>
        <div>尺寸: {{ currentImageInfo.width }} × {{ currentImageInfo.height }}</div>
        <div>类型: {{ detectedFileType }}</div>
        <div>缩放: {{ (scale * 100).toFixed(0) }}%</div>
      </div>
    </div>
  </div>
</template>

<script>
import { getSeriesImages } from '@/api/pacs/dicom/dicom.js'
import { createQiniuImageIds } from "@/utils/dicom/dicom";
import { getSeriseAllList } from "@/api/pacs/serise/serise"

export default {
  name: 'StudyDetail',
  data() {
    return {
      loading: false,
      initializing: false,
      imageLoading: false,
      error: '',
      seriesInstanceUid: '',
      seriesInstanceUidOptions: [],
      studyId: '',
      showDebugInfo: false,
      
      // 图像相关
      imageUrls: [],
      currentImageIndex: -1,
      currentImageUrl: '',
      currentImageData: null,
      currentImageInfo: null,
      detectedFileType: '未知',
      dataSize: 0,
      currentLoadMethod: '',
      
      // 显示控制
      scale: 1,
      offsetX: 0,
      offsetY: 0,
      
      // 交互状态
      isDragging: false,
      lastMouseX: 0,
      lastMouseY: 0,
      
      viewerInitialized: false
    }
  },
  mounted() {
    this.studyId = this.$route.query.studyId;
    if (this.studyId) {
      this.fetchSeriesList(this.studyId);
    } else {
      this.error = '未找到检查ID'
    }
    
    // 初始化 Canvas
    this.initCanvas();
  },
  methods: {
    // 序列选择变化处理
    handleSeriesChange(value) {
      console.log('选择的序列:', value);
    },

    // 初始化 Canvas
    initCanvas() {
      this.canvas = this.$refs.canvasRef;
      if (this.canvas) {
        this.ctx = this.canvas.getContext('2d');
        this.updateCanvasSize();
        window.addEventListener('resize', this.updateCanvasSize);
      }
    },

    // 更新 Canvas 尺寸
    updateCanvasSize() {
      if (this.canvas) {
        const container = this.canvas.parentElement;
        this.canvas.width = container.clientWidth;
        this.canvas.height = container.clientHeight - 40;
      }
    },

    // 初始化查看器
    async initViewer() {
      this.initializing = true;
      this.error = '';
      
      try {
        this.viewerInitialized = true;
        console.log("查看器初始化完成");
      } catch (err) {
        console.error("初始化失败:", err);
        this.error = `初始化失败: ${err.message}`;
      } finally {
        this.initializing = false;
      }
    },

    // 修复图像 URL 格式
    fixImageUrls(imageIds) {
      return imageIds.map(url => {
        // 移除所有协议前缀，只保留纯 URL
        let fixedUrl = url.replace(/^(qiniu:|dicom:|wadouri:|manual:)+/, '');
        
        // 确保是有效的 HTTP URL
        if (!fixedUrl.startsWith('http')) {
          fixedUrl = `http://${fixedUrl}`;
        }
        
        console.log(`原始URL: ${url} -> 修复后: ${fixedUrl}`);
        return fixedUrl;
      });
    },

    // 详细的文件类型检测
    detectFileTypeDetailed(uint8Array) {
      this.dataSize = uint8Array.length;
      
      // DICOM 文件签名 (DICM)
      if (uint8Array.length >= 132) {
        if (uint8Array[128] === 0x44 && uint8Array[129] === 0x49 && 
            uint8Array[130] === 0x43 && uint8Array[131] === 0x4D) {
          return 'DICOM';
        }
      }
      
      // JPEG 文件签名
      if (uint8Array.length >= 3) {
        if (uint8Array[0] === 0xFF && uint8Array[1] === 0xD8 && uint8Array[2] === 0xFF) {
          // 检查 JPEG 类型
          if (uint8Array[3] === 0xE0) return 'JPEG (JFIF)';
          if (uint8Array[3] === 0xE1) return 'JPEG (Exif)';
          return 'JPEG';
        }
      }
      
      // PNG 文件签名
      if (uint8Array.length >= 8) {
        if (uint8Array[0] === 0x89 && uint8Array[1] === 0x50 && 
            uint8Array[2] === 0x4E && uint8Array[3] === 0x47 &&
            uint8Array[4] === 0x0D && uint8Array[5] === 0x0A &&
            uint8Array[6] === 0x1A && uint8Array[7] === 0x0A) {
          return 'PNG';
        }
      }
      
      // BMP 文件签名
      if (uint8Array.length >= 2) {
        if (uint8Array[0] === 0x42 && uint8Array[1] === 0x4D) {
          return 'BMP';
        }
      }
      
      // GIF 文件签名
      if (uint8Array.length >= 6) {
        if (uint8Array[0] === 0x47 && uint8Array[1] === 0x49 && uint8Array[2] === 0x46 &&
            uint8Array[3] === 0x38 && (uint8Array[4] === 0x37 || uint8Array[4] === 0x39) && 
            uint8Array[5] === 0x61) {
          return 'GIF';
        }
      }
      
      // 检查是否是纯 DICOM 数据（没有前缀）
      if (this.looksLikeDicomData(uint8Array)) {
        return 'DICOM数据';
      }
      
      return '未知格式';
    },

    // 检查是否像 DICOM 数据
    looksLikeDicomData(uint8Array) {
      // DICOM 数据通常包含特定的标签结构
      // 这里做一个简单的启发式检查
      if (uint8Array.length < 8) return false;
      
      // 检查前几个字节是否看起来像 DICOM 标签
      // 这是一个简化的检查
      for (let i = 0; i < Math.min(100, uint8Array.length - 4); i += 2) {
        const group = (uint8Array[i] << 8) | uint8Array[i + 1];
        const element = (uint8Array[i + 2] << 8) | uint8Array[i + 3];
        
        // 检查是否是有效的 DICOM 标签范围
        if (group >= 0x0000 && group <= 0xFFFF && 
            element >= 0x0000 && element <= 0xFFFF) {
          return true;
        }
      }
      
      return false;
    },

    // 加载 DICOM 图像
    async loadDicomImages() {
      if (!this.seriesInstanceUid) {
        this.error = "请选择序列实例";
        return;
      }
      
      this.loading = true;
      this.error = '';
      
      try {
        console.log("获取序列图像数据...");
        const series = await getSeriesImages(this.studyId, this.seriesInstanceUid);
        
        if (!series.data || !series.data.images || series.data.images.length === 0) {
          throw new Error('未找到图像数据');
        }
        
        const tempImageIds = series.data.images;
        let imageUrls = createQiniuImageIds(tempImageIds);
        console.log("原始图像URL列表:", imageUrls);

        if (imageUrls.length === 0) {
          throw new Error('无法生成有效的图像 URL');
        }

        // 修复 URL 格式
        this.imageUrls = this.fixImageUrls(imageUrls);
        console.log("修复后的图像URL列表:", this.imageUrls);

        // 加载第一张图像
        if (this.imageUrls.length > 0) {
          await this.loadImage(0);
        }
        
        console.log("DICOM 图像加载完成");
      } catch (err) {
        console.error("加载 DICOM 图像失败:", err);
        this.error = `加载失败: ${err.message}`;
      } finally {
        this.loading = false;
      }
    },

    // 加载单张图像
    async loadImage(index) {
      if (index < 0 || index >= this.imageUrls.length) return;
      
      this.imageLoading = true;
      this.error = '';
      this.currentImageUrl = this.imageUrls[index];
      
      try {
        const url = this.imageUrls[index];
        console.log(`正在加载图像 ${index}:`, url);
        
        // 获取原始数据并分析
        const arrayBuffer = await this.fetchRawData(url);
        const uint8Array = new Uint8Array(arrayBuffer);
        
        // 检测文件类型
        this.detectedFileType = this.detectFileTypeDetailed(uint8Array);
        console.log(`检测到的文件类型: ${this.detectedFileType}, 数据大小: ${arrayBuffer.byteLength} bytes`);
        
        // 根据文件类型选择合适的加载方式
        await this.loadBasedOnFileType(arrayBuffer, url, index);
        
      } catch (err) {
        console.error(`加载图像 ${index} 失败:`, err);
        this.error = `图像加载失败: ${err.message} (类型: ${this.detectedFileType})`;
        
        // 显示错误图像
        this.showErrorImage();
      } finally {
        this.imageLoading = false;
      }
    },

    // 获取原始数据
    async fetchRawData(url) {
      const response = await fetch(url, {
        method: 'GET',
        mode: 'cors',
        cache: 'no-cache'
      });

      if (!response.ok) {
        throw new Error(`获取数据失败: ${response.status} ${response.statusText}`);
      }

      return await response.arrayBuffer();
    },

    // 根据文件类型加载
    async loadBasedOnFileType(arrayBuffer, url, index) {
      const uint8Array = new Uint8Array(arrayBuffer);
      
      // 尝试多种加载方式
      const methods = [
        { name: '直接图像加载', method: () => this.tryDirectImageLoad(url, index) },
        { name: 'Blob URL 加载', method: () => this.tryBlobUrlLoad(arrayBuffer, index) },
        { name: 'Base64 加载', method: () => this.tryBase64Load(uint8Array, index) },
        { name: 'Canvas 直接绘制', method: () => this.tryCanvasDirectDraw(uint8Array, index) }
      ];

      for (let method of methods) {
        try {
          this.currentLoadMethod = method.name;
          console.log(`尝试 ${method.name}...`);
          await method.method();
          console.log(`${method.name} 成功`);
          return;
        } catch (err) {
          console.warn(`${method.name} 失败:`, err.message);
        }
      }
      
      throw new Error('所有加载方式都失败了');
    },

    // 方法1: 直接图像加载
    async tryDirectImageLoad(url, index) {
      return new Promise((resolve, reject) => {
        const img = new Image();
        img.crossOrigin = "anonymous";
        
        const timeout = setTimeout(() => {
          reject(new Error('直接图像加载超时'));
        }, 10000);
        
        img.onload = () => {
          clearTimeout(timeout);
          this.setImageData(img, index);
          resolve();
        };
        
        img.onerror = () => {
          clearTimeout(timeout);
          reject(new Error('直接图像加载失败'));
        };
        
        img.src = url + '?t=' + Date.now();
      });
    },

    // 方法2: Blob URL 加载
    async tryBlobUrlLoad(arrayBuffer, index) {
      return new Promise((resolve, reject) => {
        // 尝试不同的 MIME 类型
        const mimeTypes = [
          'image/jpeg',
          'image/png',
          'image/gif',
          'image/bmp',
          'application/dicom',
          'application/octet-stream'
        ];

        let currentTry = 0;

        const tryWithMimeType = () => {
          if (currentTry >= mimeTypes.length) {
            reject(new Error('所有 MIME 类型都失败'));
            return;
          }

          const mimeType = mimeTypes[currentTry];
          const blob = new Blob([arrayBuffer], { type: mimeType });
          const url = URL.createObjectURL(blob);
          const img = new Image();

          img.onload = () => {
            URL.revokeObjectURL(url);
            this.setImageData(img, index);
            resolve();
          };

          img.onerror = () => {
            URL.revokeObjectURL(url);
            currentTry++;
            setTimeout(tryWithMimeType, 0);
          };

          console.log(`尝试 MIME 类型: ${mimeType}`);
          img.src = url;
        };

        tryWithMimeType();
      });
    },

    // 方法3: Base64 加载
    async tryBase64Load(uint8Array, index) {
      return new Promise((resolve, reject) => {
        // 将二进制数据转换为 base64
        let binary = '';
        for (let i = 0; i < uint8Array.length; i++) {
          binary += String.fromCharCode(uint8Array[i]);
        }
        const base64 = btoa(binary);
        
        // 尝试不同的数据URL格式
        const dataUrlFormats = [
          `data:image/jpeg;base64,${base64}`,
          `data:image/png;base64,${base64}`,
          `data:image/gif;base64,${base64}`,
          `data:application/octet-stream;base64,${base64}`
        ];

        let currentTry = 0;

        const tryWithFormat = () => {
          if (currentTry >= dataUrlFormats.length) {
            reject(new Error('所有数据URL格式都失败'));
            return;
          }

          const dataUrl = dataUrlFormats[currentTry];
          const img = new Image();

          img.onload = () => {
            this.setImageData(img, index);
            resolve();
          };

          img.onerror = () => {
            currentTry++;
            setTimeout(tryWithFormat, 0);
          };

          console.log(`尝试数据URL格式: ${dataUrl.substring(0, 50)}...`);
          img.src = dataUrl;
        };

        tryWithFormat();
      });
    },

    // 方法4: Canvas 直接绘制（用于 DICOM 数据）
    async tryCanvasDirectDraw(uint8Array, index) {
      // 这是一个简化的 DICOM 渲染器
      // 实际应用中需要使用专业的 DICOM 解析库
      
      // 创建灰度图像
      const width = 512; // 假设的宽度
      const height = 512; // 假设的高度
      
      const img = new Image();
      const canvas = document.createElement('canvas');
      canvas.width = width;
      canvas.height = height;
      const ctx = canvas.getContext('2d');
      
      const imageData = ctx.createImageData(width, height);
      
      // 简单的灰度渲染（这只是一个示例）
      for (let i = 0; i < Math.min(width * height, uint8Array.length); i++) {
        const value = uint8Array[i];
        const pos = i * 4;
        imageData.data[pos] = value;     // R
        imageData.data[pos + 1] = value; // G
        imageData.data[pos + 2] = value; // B
        imageData.data[pos + 3] = 255;   // A
      }
      
      ctx.putImageData(imageData, 0, 0);
      
      return new Promise((resolve) => {
        img.onload = () => {
          this.setImageData(img, index);
          resolve();
        };
        img.src = canvas.toDataURL();
      });
    },

    // 设置图像数据
    setImageData(img, index) {
      this.currentImageData = img;
      this.currentImageInfo = {
        width: img.width,
        height: img.height
      };
      this.currentImageIndex = index;
      this.renderImage();
    },

    // 分析当前图像数据
    async analyzeCurrentImage() {
      if (!this.currentImageUrl) return;
      
      try {
        const arrayBuffer = await this.fetchRawData(this.currentImageUrl);
        const uint8Array = new Uint8Array(arrayBuffer);
        
        const analysis = {
          文件类型: this.detectFileTypeDetailed(uint8Array),
          文件大小: `${arrayBuffer.byteLength} bytes`,
          前16字节: Array.from(uint8Array.slice(0, 16)).map(b => b.toString(16).padStart(2, '0')).join(' '),
          数据预览: Array.from(uint8Array.slice(0, 100)).join(', ')
        };
        
        console.log('图像数据分析:', analysis);
        alert(`图像数据分析:\n${JSON.stringify(analysis, null, 2)}`);
      } catch (err) {
        alert(`分析失败: ${err.message}`);
      }
    },

    // 显示错误图像
    showErrorImage() {
      if (!this.ctx) return;
      
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      
      this.ctx.fillStyle = '#333';
      this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
      
      this.ctx.fillStyle = '#fff';
      this.ctx.font = '14px Arial';
      this.ctx.textAlign = 'center';
      this.ctx.fillText('图像加载失败', this.canvas.width / 2, this.canvas.height / 2 - 60);
      this.ctx.fillText(`文件类型: ${this.detectedFileType}`, this.canvas.width / 2, this.canvas.height / 2 - 40);
      this.ctx.fillText(`数据大小: ${this.dataSize} bytes`, this.canvas.width / 2, this.canvas.height / 2 - 20);
      this.ctx.fillText('请使用"分析图像数据"按钮查看详细信息', this.canvas.width / 2, this.canvas.height / 2);
    },

    // 渲染图像到 Canvas
    renderImage() {
      if (!this.currentImageData || !this.ctx) {
        this.showErrorImage();
        return;
      }
      
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      
      const img = this.currentImageData;
      const renderWidth = img.width * this.scale;
      const renderHeight = img.height * this.scale;
      
      let offsetX = (this.canvas.width - renderWidth) / 2 + this.offsetX;
      let offsetY = (this.canvas.height - renderHeight) / 2 + this.offsetY;
      
      const maxOffsetX = Math.max(0, (renderWidth - this.canvas.width) / 2);
      const maxOffsetY = Math.max(0, (renderHeight - this.canvas.height) / 2);
      offsetX = Math.max(-maxOffsetX, Math.min(maxOffsetX, offsetX));
      offsetY = Math.max(-maxOffsetY, Math.min(maxOffsetY, offsetY));
      
      this.ctx.imageSmoothingEnabled = true;
      this.ctx.imageSmoothingQuality = 'high';
      this.ctx.drawImage(img, offsetX, offsetY, renderWidth, renderHeight);
    },

    // 放大
    zoomIn() {
      this.scale = Math.min(5, this.scale * 1.2);
      this.renderImage();
    },

    // 缩小
    zoomOut() {
      this.scale = Math.max(0.1, this.scale / 1.2);
      this.renderImage();
    },

    // 重置视图
    resetView() {
      this.scale = 1;
      this.offsetX = 0;
      this.offsetY = 0;
      this.renderImage();
    },

    // 上一张图像
    prevImage() {
      if (this.currentImageIndex > 0) {
        this.loadImage(this.currentImageIndex - 1);
      }
    },

    // 下一张图像
    nextImage() {
      if (this.currentImageIndex < this.imageUrls.length - 1) {
        this.loadImage(this.currentImageIndex + 1);
      }
    },

    // 鼠标滚轮事件（缩放）
    handleWheel(event) {
      event.preventDefault();
      const delta = -Math.sign(event.deltaY);
      this.scale = Math.max(0.1, Math.min(5, this.scale + delta * 0.1));
      this.renderImage();
    },

    // 鼠标按下事件（开始拖拽）
    handleMouseDown(event) {
      this.isDragging = true;
      this.lastMouseX = event.clientX;
      this.lastMouseY = event.clientY;
      this.canvas.style.cursor = 'grabbing';
    },

    // 鼠标移动事件（拖拽）
    handleMouseMove(event) {
      if (this.isDragging) {
        const deltaX = event.clientX - this.lastMouseX;
        const deltaY = event.clientY - this.lastMouseY;
        
        this.offsetX += deltaX;
        this.offsetY += deltaY;
        
        this.lastMouseX = event.clientX;
        this.lastMouseY = event.clientY;
        
        this.renderImage();
      }
    },

    // 鼠标释放事件（结束拖拽）
    handleMouseUp() {
      this.isDragging = false;
      this.canvas.style.cursor = 'grab';
    },

    // 获取序列列表
    async fetchSeriesList(studyIdValue) {
      this.loading = true;
      this.seriesInstanceUidOptions = [];
      this.seriesInstanceUid = '';

      try {
        const response = await getSeriseAllList({ studyId: studyIdValue });
        console.log("序列列表:", response);
        
        if (response.data && response.data.length > 0) {
          this.seriesInstanceUidOptions = response.data;
          this.seriesInstanceUid = response.data[0].seriseId;
        } else {
          this.error = '未找到序列数据';
        }
      } catch (err) {
        console.error("获取序列列表失败:", err);
        this.error = `获取序列失败: ${err.message}`;
      } finally {
        this.loading = false;
      }
    }
  },

  beforeUnmount() {
    window.removeEventListener('resize', this.updateCanvasSize);
  }
}
</script>

<style scoped>
/* 样式保持不变，与之前相同 */
.app-container {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}

.header-controls {
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  padding: 15px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.debug-info {
  background: #f0f0f0;
  padding: 15px;
  border-radius: 6px;
  margin-bottom: 15px;
  font-family: monospace;
  font-size: 12px;
  line-height: 1.5;
}

.image-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 15px;
  flex-wrap: wrap;
}

.image-operations {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-left: 20px;
}

.image-counter {
  padding: 0 10px;
  font-weight: bold;
  color: #409eff;
}

.status-message {
  padding: 12px 16px;
  background-color: #e6f7ff;
  border: 1px solid #91d5ff;
  border-radius: 6px;
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: #1890ff;
}

.error-message {
  padding: 12px 16px;
  background-color: #fff2f0;
  border: 1px solid #ffccc7;
  border-radius: 6px;
  margin-bottom: 15px;
  display: flex;
  align-items: center;
  gap: 8px;
  color: #ff4d4f;
}

.viewer-container {
  position: relative;
  width: 100%;
  height: 600px;
  background-color: #000;
  border: 1px solid #ddd;
  border-radius: 8px;
  margin-bottom: 15px;
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  overflow: hidden;
}

.dicom-canvas {
  width: 100%;
  height: 100%;
  cursor: grab;
  display: block;
}

.dicom-canvas:active {
  cursor: grabbing;
}

.loading-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.7);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 16px;
  gap: 10px;
}

.image-info {
  position: absolute;
  bottom: 10px;
  left: 10px;
  background: rgba(0, 0, 0, 0.7);
  color: white;
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 12px;
  line-height: 1.4;
}
</style>